﻿/**
 * ColorMatrix
 * this class is designed to be used with the flash.filters.ColorMatrixFilter class
 * 
 * @author		Allen Chou
 * @version		1.0.2 (last update: Feb 6 2008)
 * @link		http://cjcat2266.deviantart.com
 */

package idv.cjcat.geom.matrices {
	
	/**
	 * This class contains constants and methods for creating matrices that can be used with <code>flash.filters.ColorMatrixFilter</code>.
	 * 
	 * @example
	 * <listing version="3.0">
	 * import flash.filters.ColorMatrixFilter;
	 * import idv.cjcat.geom.matrices.ColorMatrix;
	 * 
	 * pic.filters = [ColorMatrixFilter(ColorMatrix.DIGITAL_NEGATIVE)];
	 * //inverts the color
	 * 
	 * pic.filters = [ColorMatrixFilter(ColorMatrix.GRAYSCALE)];
	 * //desaturates the color
	 * 
	 * pic.filters = [new ColorMatrixFilter(ColorMatrix.contrast(0.5)];
	 * //enhances contrast</listing>
	 */
	public class ColorMatrix {
		
		//luminace of red, green, and blue.
		private static var rw:Number = 0.3086;
		private static var gw:Number = 0.6094;
		private static var bw:Number = 0.0820;
		
		//updated in version 1.0.1 (changed from public static getter to public static constant)
		/**
		 * Identity matrix.
		 */
		public static const IDENTITY:Array = [1, 0, 0, 0, 0,
		                                      0, 1, 0, 0, 0,
											  0, 0, 1, 0, 0,
											  0, 0, 0, 1, 0];
		
		//updated in version 1.0.1 (changed from public static getter to public static constant)
		/**
		 * Digital-negative matrix.
		 */
		public static const DIGITAL_NEGATIVE:Array = [-1,  0,  0,  0, 255,
											           0, -1,  0,  0, 255,
													   0,  0, -1,  0, 255,
													   0,  0,  0,  1,   0];

		//updated in version 1.0.1 (changed from public static getter to public static constant)
		/**
		 * Grayscale matrix.
		 */
		public static const GRAYSCALE:Array = [rw, gw, bw, 0, 0,
											   rw, gw, bw, 0, 0,
											   rw, gw, bw, 0, 0,
											    0,  0,  0, 1, 0];
		
		//updated in version 1.0.2 (enhanced calculation efficiency)
		/**
		 * Returns a saturation matrix.
		 * @param	level Zero gives a grayscale matrix; one gives a fully-saturated matrix; one over three (1/3) gives an identity matrix.
		 * @return The saturation matrix.
		 */
		public static function saturation(level:Number = 1/3):Array {
			if (!((level >= 0) && (level <= 1))) {
				if (level > 1) {
					level = 1;
				} else {
					level = 0;
				}
			}
			var level2:Number = level * 3;
			var level3:Number = 1 - level2;
			
			return [level3 * rw + level2,           level3 * gw,           level3 * bw, 0, 0,
			                 level3 * rw,  level3 * gw + level2,           level3 * bw, 0, 0,
					         level3 * rw,           level3 * gw,  level3 * bw + level2, 0, 0,
				               	       0,                     0,                     0, 1, 0];
		}
		
		//updated in version 1.0.2 (enhanced calculation efficiency)
		/**
		 * Returns a tint matrix.
		 * @param	redTint    One gives complete red; negative one gives no red at all; zero makes no change.
		 * @param	greenTint  One gives complete green; negative one gives no green at all; zero makes no change.
		 * @param	blueTint   One gives complete blue; negative one gives no blue at all; zero makes no change.
		 * @return The tint matrix.
		 */
		public static function tint(redTint:Number = 0, greenTint:Number = 0, blueTint:Number = 0):Array {
			if (!((redTint >= -1) && (redTint <= 1))) {
				if (redTint > 1) {
					redTint = 1;
				} else {
					redTint = -1;
				}
			}
			if (!((greenTint >= -1) && (greenTint <= 1))) {
				if (greenTint > 1) {
					greenTint = 1;
				} else {
					greenTint = -1;
				}
			}
			if (!((blueTint >= -1) && (blueTint <= 1))) {
				if (blueTint > 1) {
					blueTint = 1;
				} else {
					blueTint = -1;
				}
			}
			
			return [1, 0, 0, 0,   redTint * 255,
			        0, 1, 0, 0, greenTint * 255,
					0, 0, 1, 0,  blueTint * 255,
					0, 0, 0, 1,               0];
		}
		
		//updated in version 1.0.2 (enhanced calculation efficiency)
		/**
		 * Returns a brightness matrix.
		 * @param	level One gives complete white; negative one gives complete black; zero gives an identity matrix.
		 * @return The brightness matrix.
		 */
		public static function brightness(level:Number = 0):Array {
			if (!((level >= -1) && (level <= 1))) {
				if (level > 1) {
					level = 1;
				} else {
					level = -1;
				}
			}
			var level2:Number = level * 255;
			
			return [1, 0, 0, 0, level2,
			        0, 1, 0, 0, level2,
					0, 0, 1, 0, level2,
					0, 0, 0, 1,      0];
		}
		
		//updated in version 1.0.2 (enhanced calculation efficiency)
		/**
		 * Returns a constrast matrix.
		 * @param	level One gives the highest contrast; zero gives zero contrast; one over eleven (1/11) gives an identity matrix.
		 * @return The contrast matrix.
		 */
		public static function contrast(level:Number):Array {
			if (!((level >= 0) && (level <= 1))) {
				if (level > 1) {
					level = 1;
				} else {
					level = 0;
				}
			}
			var scale:Number = level * 11;
			var offset:Number = 63.5 - (level * 698.5);
			
			return [scale,     0,     0, 0, offset,
			            0, scale,     0, 0, offset,
					    0,     0, scale, 0, offset,
					    0,     0,     0, 1,      0];
		}
	}
}